<?php

namespace App\Http\Controllers\Api\V1;

use App\Libs\Log;
use App\Models\OrderList;
use App\Models\PutPeriod;
use App\Models\Student;
use App\Models\Subscribe;
use App\Repositories\OrderListRepository;
use App\Repositories\SubscribesRepository;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Facades\JWTAuth;
use App\Libs\Alipay\Notify;
use App\Libs\Wxpay\WxPayApi;
use App\Libs\Wxpay\JsApiPay;
use App\Libs\Wxpay\WxPayUnifiedOrder;
use App\Libs\Wxpay\WxPayConfig;
use App\Libs\Wxpay\WxPayNotify;
use App\Libs\WxApp\WxPayApi as WxAppPayApi;
use App\Libs\WxApp\WxPayUnifiedOrder as WxAppPayUnifiedOrder;
use App\Libs\WxApp\WxPayConfig as WxAppPayConfig;
use App\Libs\WxApp\WxPayNotify as WxAppPayNotify;

class PayController extends BaseController
{


    protected $orderlist;
    protected $subscribe;

    public function __construct(
        OrderListRepository $orderlist,
        SubscribesRepository $subscribe
    )
    {
        $this->orderlist = $orderlist;
        $this->subscribe = $subscribe;
    }


    /**
     * @api {get} /pay/video 视频支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/video
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     *
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function videoPay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        $data['title'] = '视频学习支付';
        $data['price'] = config('pay.video_money');
        $data['num'] = 1;

        $order_info = $this->orderlist->store($data, $user);

        if($order_info){

            $alipay_config = config('pay.alipay_config');

            $ali = array(
                'service' => 'mobile.securitypay.pay',
                'partner' => trim($alipay_config['partner']),
                '_input_charset' => trim(strtolower($alipay_config['input_charset'])),
                'seller_id' => trim($alipay_config['partner']),//'13890341236@163.com',//支付宝账号
                'notify_url' => trim($alipay_config['notify_url']),
                'out_trade_no' => $order_info->ordid,//商户网站唯一订单号
                'subject' =>  '视频学习支付',//商品名称
                'payment_type' => 1,//支付类型
                'total_fee' => $data['price'],//总金额
                'body' =>  'video_pay'  //商品详情
            );

            $ali = $this->argSort($ali);
            $str = '';
            foreach ($ali as $key => $val) {
                if ($key == 'sign_type' || $key == 'sign') {
                    continue;
                } else {
                    if ($str == '') {
                        $str = "{$key}=\"{$val}\"";
                    } else {
                        $str = "{$str}&{$key}=\"{$val}\"";
                    }
                }
            }

            $sign = urlencode($this->sign($str, $alipay_config['private_key_path']));
            $ali['sign'] = $sign;
            $ali['sign_type'] = 'RSA';

            $str = $str . '&sign=' . '"' . $sign . '"' . '&sign_type=' . '"' . $ali['sign_type'] . '"';//传给支付宝接口的数据
            $arr['defray'] = $str;

            return $this->successResponse('操作成功',['data' => $arr]);

        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }

    }


    /**
     * @api {get} /pay/subscribe 预约支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/subscribe
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     * @apiParam {Number} [subscribe_id]  subscribe_id
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function subscribePay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        $sub_id = $request->input('subscribe_id');
        $subscribe_info = Subscribe::find($sub_id);

//        $data['title'] = '预约学车支付';
//        $data['price'] = $subscribe_info->money;
//        $data['num'] = 1;
//        $data['id'] = $sub_id;
//
//        $order_info = $this->orderlist->store($data, $user);

        $order_info = OrderList::where('productid', $subscribe_info->id)->first();

        if($order_info){

            $alipay_config = config('pay.alipay_config');

            $ali = array(
                'service' => 'mobile.securitypay.pay',
                'partner' => trim($alipay_config['partner']),
                '_input_charset' => trim(strtolower($alipay_config['input_charset'])),
                'seller_id' => trim($alipay_config['partner']),//'13890341236@163.com',//支付宝账号
                'notify_url' => trim($alipay_config['notify_url']),
                'out_trade_no' => $order_info->ordid,//商户网站唯一订单号
                'subject' =>  '预约学车支付',//商品名称
                'payment_type' => 1,//支付类型
                'total_fee' => $data['price'],//总金额
                'body' =>  'subscribe_pay',  //商品详情
            );

            $ali = $this->argSort($ali);
            $str = '';
            foreach ($ali as $key => $val) {
                if ($key == 'sign_type' || $key == 'sign') {
                    continue;
                } else {
                    if ($str == '') {
                        $str = "{$key}=\"{$val}\"";
                    } else {
                        $str = "{$str}&{$key}=\"{$val}\"";
                    }
                }
            }

            $sign = urlencode($this->sign($str, $alipay_config['private_key_path']));
            $ali['sign'] = $sign;
            $ali['sign_type'] = 'RSA';

            $str = $str . '&sign=' . '"' . $sign . '"' . '&sign_type=' . '"' . $ali['sign_type'] . '"';//传给支付宝接口的数据
            $arr['defray'] = $str;

            return $this->successResponse('操作成功',['data' => $arr]);

        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }

    }


    /**
     * 支付宝回调
     */
    public function alinotify(Request $request)
    {
        $alipay_config=config('pay.alipay_config');
        //计算得出通知验证结果
        $alipayNotify = new Notify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();
        $post = $_POST;
        $post['errorcode'] = $verify_result;


        $log = Log::get('pay_logs');
        $log->addInfo('video_pay'.json_encode($_POST));

        /*if($verify_result) {*/
        //验证成功
        //获取支付宝的通知返回参数，可参考技术文档中服务器异步通知参数列表
        $out_trade_no   = $_POST['out_trade_no'];      //商户订单号
        $trade_no       = $_POST['trade_no'];          //支付宝交易号
        $trade_status   = $_POST['trade_status'];      //交易状态
        $total_fee      = $_POST['total_fee'];         //交易金额
        $notify_id      = $_POST['notify_id'];         //通知校验ID。
        $notify_time    = $_POST['notify_time'];       //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。
        $buyer_email    = $_POST['buyer_email'];       //买家支付宝帐号；
        $parameter = array(
            'payment_type'    => 'alipay',
            "out_trade_no"     => $out_trade_no, //商户订单编号；
            "trade_no"     => $trade_no,     //支付宝交易号；
            "total_fee"     => $total_fee,    //交易金额；
            "trade_status"     => $trade_status, //交易状态
            "notify_id"     => $notify_id,    //通知校验ID。
            "notify_time"   => $notify_time,  //通知的发送时间。
            "buyer_email"   => $buyer_email,  //买家支付宝帐号；
        );

        if($_POST['trade_status'] == 'TRADE_FINISHED') {
            return 'no';
        }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {

            $order_info = OrderList::where(['ordid'=>$out_trade_no])->first();//查找当前订单信息

            $log->addInfo('video_pay_order_info'.json_encode($order_info));
            if($order_info->ordstatus == 0){
                //进行订单处理，并传送从支付宝返回的参数；
                $data['payment_type']          =$parameter['payment_type'];
                $data['payment_trade_no']      =$parameter['trade_no'];
                $data['payment_trade_status']  =$parameter['trade_status'];
                $data['payment_notify_id']     =$parameter['notify_id'];
                $data['payment_notify_time']   =$parameter['notify_time'];
                $data['payment_buyer_email']   =$parameter['buyer_email'];
                $data['ordstatus']             =1;

                OrderList::where(['ordid'=>$out_trade_no])->update($data);

                if($_POST['body'] == 'video_pay'){

                    //修改学员视频支付状态
                    $rs = Student::where(['id'=>$order_info->userid])->update(['video_pay'=>1]);
                }elseif($_POST['body'] == 'subscribe_pay'){

                    //修改预约支付状态
                    $rs = Subscribe::where(['id' => $order_info->productid])->update(['paystatus' => 1]);
                }

                if(!$rs){
                    return 'no';
                }

            }

            return 'success';
        }

    }


    private  function argSort($para)
    {
        ksort($para);
        reset($para);
        return $para;
    }
    //RSA签名
    private function sign($data,$private_key_path)
    {
        //读取私钥文件
        $priKey = file_get_contents($private_key_path);//私钥文件路径
        //转换为openssl密钥，必须是没有经过pkcs8转换的私钥
        $res = openssl_get_privatekey($priKey);
        //调用openssl内置签名方法，生成签名$sign
        openssl_sign($data, $sign, $res);
        //释放资源
        openssl_free_key($res);
        //base64编码
        $sign = base64_encode($sign);
        return $sign;
    }


    /**
     * @api {get} /pay/WxPubVideoPay 微信公众号视频支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/WxPubVideoPay
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     * @apiParam {String} [openid]  openid
     *
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function WxPubVideoPay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        if(!$openId = $request->input('openid')){
            return $this->errorResponse('openid必传',['data' => '']);
        }

        if(!$product_id = $request->input('video_id')){
            return $this->errorResponse('video_id必传',['data' => '']);
        }

        $data['title'] = '视频学习支付';
        $data['price'] = config('pay.video_money');
        $data['id'] = $product_id;
        $data['num'] = 1;

        $order_info = $this->orderlist->store($data, $user);

        if($order_info){

            //②、统一下单
            $tools = new JsApiPay();

            $input = new WxPayUnifiedOrder();
            $input->SetBody("视频学习支付");
            $input->SetAttach("video_pay");
            $input->SetOut_trade_no($order_info->ordid);
            $input->SetTotal_fee($data['price'] * 100);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url("http://app.stjp360.com/api/pay/wxnotify");
            $input->SetTrade_type("JSAPI");
            $input->SetOpenid($openId);
            $input->SetProduct_id($product_id);
            $order = WxPayApi::unifiedOrder($input);

            $jsApiParameters = $tools->GetJsApiParameters($order);

            return $this->successResponse('操作成功',['data' => $jsApiParameters]);
        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }
    }



    /**
     * @api {get} /pay/WxAppVideoPay 微信App视频支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/WxAppVideoPay
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     *
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function WxAppVideoPay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        $data['title'] = '视频学习支付';
        $data['price'] = config('pay.video_money');
        $data['num'] = 1;

        $order_info = $this->orderlist->store($data, $user);

        if($order_info){

            //②、统一下单
            $input = new WxAppPayUnifiedOrder();
            $input->SetBody("视频学习支付");
            $input->SetAttach("video_pay");
            $input->SetOut_trade_no($order_info->ordid);
            $input->SetTotal_fee($data['price'] * 100);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url("http://app.stjp360.com/api/pay/wxAppnotify");
            $input->SetTrade_type("APP");
            $order = WxAppPayApi::unifiedOrder($input);

            if((array_key_exists('return_code', $order) && $order['return_code'] == 'SUCCESS')
                && (array_key_exists('result_code', $order) && $order['result_code'] == 'SUCCESS')){

                $info['appId'] = $order['appid'];
                $info['partnerId'] = $order['mch_id'];
                $info['prepayId'] = $order['prepay_id'];
                $info['nonceStr'] = $order['nonce_str'];

                $sign = '';
                $sign['appid'] = $order['appid'];
                $sign['partnerid'] = $order['mch_id'];
                $sign['prepayid'] = $order['prepay_id'];
                $sign['noncestr'] = $order['nonce_str'];
                $sign['timestamp'] = time();
                $sign['package'] = 'Sign=WXPay';

                $info['timeStamp'] = $sign['timestamp'];

                $sign = $this->WxSign($sign);
                $info['sign'] = $sign;

                return $this->successResponse('操作成功',['data' => $info]);
            }else{
                return $this->errorResponse('创建订单失败',['data' => '']);
            }

        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }
    }



    /**
     * @api {get} /pay/WxPubSubscribePay 微信公众号预约支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/WxPubSubscribePay
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     * @apiParam {String} [openid]  openid
     * @apiParam {String} [subscribe_id]  subscribe_id
     *
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function WxPubSubscribePay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        $sub_id = $request->input('subscribe_id');

        if(!$openId = $request->input('openid')){
            return $this->errorResponse('openid必传',['data' => '']);
        }

        $subscribe_info = Subscribe::find($sub_id);

//        $data['title'] = '预约学车支付';
//        $data['price'] = $subscribe_info->money;
//        $data['num'] = 1;
//        $data['id'] = $sub_id;
//
//        $order_info = $this->orderlist->store($data, $user);

        $order_info = OrderList::where('productid', $subscribe_info->id)->first();

        if($order_info){

            //②、统一下单
            $tools = new JsApiPay();

            $input = new WxPayUnifiedOrder();
            $input->SetBody("预约学车支付");
            $input->SetAttach("subscribe_pay");
            $input->SetOut_trade_no($order_info->ordid);
            $input->SetTotal_fee($order_info->ordfee * 100);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url("http://app.stjp360.com/api/pay/wxnotify");
            $input->SetTrade_type("JSAPI");
            $input->SetOpenid($openId);
            $order = WxPayApi::unifiedOrder($input);

            $jsApiParameters = $tools->GetJsApiParameters($order);

            return $this->successResponse('操作成功',['data' => $jsApiParameters]);
        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }
    }


    /**
     * @api {get} /pay/WxAppSubscribePay 微信App预约支付
     * @apiDescription 支付
     * @apiGroup pay
     * @apiPermission none
     * @apiSampleRequest /api/pay/WxAppSubscribePay
     * @apiHeader {String} Authorization 用户旧的jwt-token, value已Bearer开头
     * @apiParam {String} [subscribe_id]  subscribe_id
     *
     * @apiVersion 1.0.0
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 201 Created
     *   {
     *       "message": "",
     *       "code": 200,
     *       "data": {
     *           "id":'主键',
     *           "name": "名称",
     *           "idcard": "身份证号",
     *
     *       }
     *   }
     * @apiErrorExample {json} Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "UserNotFound"
     *     }
     */
    public function WxAppSubscribePay(Request $request)
    {

        $user = JWTAuth::parseToken()->authenticate();//验证token

        if(!$this->checkToken($user->item, JWTAuth::getToken())){
            return $this->errorResponse('你的账号在其他地方登录', 401);
        }

        $sub_id = $request->input('subscribe_id');

        $subscribe_info = Subscribe::find($sub_id);

        $data['title'] = '预约学车支付';
        $data['price'] = $subscribe_info->money;
        $data['num'] = 1;
        $data['id'] = $sub_id;

        $order_info = $this->orderlist->store($data, $user);

        if($order_info){

            //②、统一下单
            $input = new WxAppPayUnifiedOrder();
            $input->SetBody("预约学车支付");
            $input->SetAttach("subscribe_pay");
            $input->SetOut_trade_no($order_info->ordid);
            $input->SetTotal_fee($data['price'] * 100);
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetNotify_url("http://app.stjp360.com/api/pay/wxAppnotify");
            $input->SetTrade_type("APP");
            $order = WxAppPayApi::unifiedOrder($input);

            if((array_key_exists('return_code', $order) && $order['return_code'] == 'SUCCESS')
                && (array_key_exists('result_code', $order) && $order['result_code'] == 'SUCCESS')){

                $info['appId'] = $order['appid'];
                $info['partnerId'] = $order['mch_id'];
                $info['prepayId'] = $order['prepay_id'];
                $info['nonceStr'] = $order['nonce_str'];

                $sign = '';
                $sign['appid'] = $order['appid'];
                $sign['partnerid'] = $order['mch_id'];
                $sign['prepayid'] = $order['prepay_id'];
                $sign['noncestr'] = $order['nonce_str'];
                $sign['timestamp'] = time();
                $sign['package'] = 'Sign=WXPay';

                $info['timeStamp'] = $sign['timestamp'];

                $sign = $this->WxSign($sign);
                $info['sign'] = $sign;

                return $this->successResponse('操作成功',['data' => $info]);
            }else{
                return $this->errorResponse('创建订单失败',['data' => '']);
            }

        }else{
            return $this->errorResponse('创建订单失败',['data' => '']);
        }
    }


    private function WxSign($values)
    {
        ksort($values);

        $buff = "";
        foreach ($values as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $string = trim($buff, "&");
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=".WxAppPayConfig::KEY;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    public function wxnotify(Request $request)
    {
        $notify = new WxPayNotify;

        $notify->handle(false);
    }


    public function wxAppnotify(Request $request)
    {
        $notify = new WxAppPayNotify;

        $notify->handle(false);
    }


















}
